using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text.RegularExpressions;
using System.Data.Linq;
using System.Linq;
using System.Collections.Generic;

namespace ClubWebsite
{
    public partial class Page : System.Web.UI.Page
    {
        protected void Page_Init()
        {
            plhContent.Controls.Clear();

            // Check if this is a new page and should be created
            DBPage page = Functions.GetDatabaseDataContext()
                .DBPages
                .Where(p => p.ID == ((Default)Master).PageID)
                .FirstOrDefault();
            if (page == null)
            {
                if (!Functions.UserHasPermissionToEditSection(Functions.SectionType.ClubNewPage, ((Default)Master).ClubID))
                {
                    throw new ApplicationException("Sorry, the page you're after isn't ready yet.");
                }
            }
            else
            {
                // Display the page content
                string HTML = page.HTML;
                if (Functions.UserHasPermissionToEditSection(Functions.SectionType.Page, ((Default)Master).PageID))
                {
                    // Replace any floating columns with non-floats
                    HTML = Regex.Replace(HTML, @"(?<=<div\sclass=""page)(left|right)column(?=(\s|""))", "non$&");
                }
                Functions.ConvertTextWithTagsIntoControls(Functions.ConvertTextWithTagsIntoHTML(HTML, Master), plhContent, this, false);
            }

            // Catch the events that the child entry controls might raise
            bool atLeastOneEntryControlExists = false;
            foreach (Control control in plhContent.Controls)
            {
                if (control is PageEntry)
                {
                    atLeastOneEntryControlExists = true;
                    ((PageEntry)control).NewEntryAboveClicked += new PageEntry.EntryOptionClickedEventHandler(Page_NewEntryAboveClicked);
                    ((PageEntry)control).NewEntryBelowClicked += new PageEntry.EntryOptionClickedEventHandler(Page_NewEntryBelowClicked);
                    ((PageEntry)control).RemoveEntryClicked += new PageEntry.EntryOptionClickedEventHandler(Page_RemoveEntryClicked);
                }
            }

            // Add a new entry if no entries exist and the user is allowed to edit the page
            if ((!atLeastOneEntryControlExists) && (Functions.UserHasPermissionToEditSection(Functions.SectionType.ClubNewPage, ((Default)Master).ClubID)))
            {
                Session[((Default)Master).PageID.ToString() + "_NewEntryIndex"] = 0;
                RenderNewEntryControl();
            }
            else
            {
                // Render a 'new entry' control if the viewstate contains an index for it
                if (Session[((Default)Master).PageID.ToString() + "_NewEntryIndex"] is int)
                {
                    // Ensure the user is logged in and is allowed to edit the page
                    if (Functions.UserHasPermissionToEditSection(Functions.SectionType.Page, ((Default)Master).PageID))
                    {
                        RenderNewEntryControl();
                    }
                    else
                    {
                        // Clear the session variable
                        Session[((Default)Master).PageID.ToString() + "_NewEntryIndex"] = null;
                    }
                }
            }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
        }

        private void Page_NewEntryAboveClicked(PageEntry entryControl)
        {
            // Find the index to insert the new entry
            int index = 0;
            foreach (Control control in plhContent.Controls)
            {
                if (control == entryControl)
                {
                    break;
                }

                // Don't increase the index if the entry is a new entry since it'll be
                // removed once the page is reloaded
                if ((!(control is PageEntry)) || (((PageEntry)control).EntryID != Guid.Empty))
                {
                    index++;
                }
            }
            // Set the view state to know where to place the contol and render the control
            Session[((Default)Master).PageID.ToString() + "_NewEntryIndex"] = index;
            Response.Redirect(Request.RawUrl.ToString());
        }

        private void Page_NewEntryBelowClicked(PageEntry entryControl)
        {
            // Find the index to insert the new entry
            int index = 0;
            foreach (Control control in plhContent.Controls)
            {
                if (control == entryControl)
                {
                    break;
                }
                index++;
            }
            // Set the view state to know where to place the contol and render the control
            Session[((Default)Master).PageID.ToString() + "_NewEntryIndex"] = index + 1;
            Response.Redirect(Request.RawUrl.ToString());
        }

        private void RenderNewEntryControl()
        {
            // Get the index of where to place the control
            int index = (int)Session[((Default)Master).PageID.ToString() + "_NewEntryIndex"];

            // Display a new entry control
            PageEntry newEntry = (PageEntry)LoadControl("PageEntry.ascx");
            if (!IsPostBack)
            {
                newEntry.EntryID = Guid.Empty;
                newEntry.CurrentMode = PageEntry.Mode.Adding;
            }
            newEntry.AddEntryClicked += new PageEntry.EntryOptionClickedEventHandler(newEntry_AddEntryClicked);
            newEntry.CancelAddEntryClicked += new PageEntry.EntryOptionClickedEventHandler(newEntry_CancelAddEntryClicked);
            plhContent.Controls.AddAt(index, newEntry);
        }

        private void newEntry_CancelAddEntryClicked(PageEntry entryControl)
        {
            // Remove the viewstate value so that the new entry control is 
            // no longer rendered
            Session.Remove(((Default)Master).PageID.ToString() + "_NewEntryIndex");
            Response.Redirect(Request.RawUrl.ToString());
        }

        private void newEntry_AddEntryClicked(PageEntry entryControl)
        {
            // Add the entry to the database
            using (MainDataClassesDataContext databaseDataContext = Functions.GetDatabaseDataContext())
            {
                Entry entry = new Entry();
                entry.ID = Guid.NewGuid();
                entry.ClubID = ((Default)Master).ClubID;
                entry.HTML = entryControl.HTML;
                databaseDataContext.Entries.InsertOnSubmit(entry);
                databaseDataContext.SubmitChanges();

                // Add the entry to this page in the correct position
                Guid entryIDToAddAfter = Guid.Empty;

                // Work backwards trying to find the entry control above this new one
                int index = (int)Session[((Default)Master).PageID.ToString() + "_NewEntryIndex"] - 1;
                while (index >= 0)
                {
                    if (plhContent.Controls[index] is PageEntry)
                    {
                        entryIDToAddAfter = ((PageEntry)plhContent.Controls[index]).EntryID;
                        break;
                    }
                    index--;
                }

                // Add this page if it is new
                DBPage page = databaseDataContext
                    .DBPages
                    .Where(p => p.ID == ((Default)Master).PageID)
                    .FirstOrDefault();
                if (page == null)
                {
                    page = new DBPage();
                    page.ID = ((Default)Master).PageID;
                    page.ClubID = ((Default)Master).ClubID;
                    page.Title = "Untitled";
                    page.UniqueTextForURLs = "";

                    // Set the unique text for the URLs. Start with one character and add another if the text
                    // isn't unique for the club.
                    bool isNotUnique;
                    do
                    {
                        page.UniqueTextForURLs = page.ID.ToString().Substring(0, page.UniqueTextForURLs.Length + 1);
                        isNotUnique = databaseDataContext
                        .DBPages
                        .Any(p => p.UniqueTextForURLs.ToLower() == page.UniqueTextForURLs.ToLower()
                            && p.ClubID == page.ClubID);
                    } while (isNotUnique);
                    databaseDataContext.DBPages.InsertOnSubmit(page);
                }

                // Update the page
                if (entryIDToAddAfter != Guid.Empty)
                {
                    page.HTML = Regex.Replace(page.HTML, String.Format("\\[entry={0}\\]", entryIDToAddAfter.ToString()), String.Format("$&\r\n[entry={0}]", entry.ID.ToString()), RegexOptions.IgnoreCase);
                }
                else
                {
                    page.HTML = String.Format("[entry={0}]\r\n{1}", entry.ID.ToString(), page.HTML);
                }
                databaseDataContext.SubmitChanges();
            }

            // Clear the viewstate so that the new entry control is no longer
            // rendererd and refresh the page
            Session.Remove(String.Format("{0}_NewEntryIndex", ((Default)Master).PageID.ToString()));
            Response.Redirect(Request.RawUrl.ToString());
        }

        private void Page_RemoveEntryClicked(PageEntry entryControl)
        {
            // Remove the entry from the HTML
            using (MainDataClassesDataContext databaseDataContext = Functions.GetDatabaseDataContext())
            {
                DBPage page = databaseDataContext
                    .DBPages
                    .Where(p => p.ID == ((Default)Master).PageID)
                    .FirstOrDefault();
                if (page != null)
                {
                    page.HTML = Regex.Replace(page.HTML, String.Format("\\[entry={0}\\](\r\n)?", entryControl.EntryID.ToString()), "", RegexOptions.IgnoreCase);
                    databaseDataContext.SubmitChanges();
                }
            }
            Response.Redirect(Request.RawUrl.ToString());
        }
    }
}
 